const fs = require('fs') // 文件模块
const path = require('path')
const inquirer = require("inquirer") // 提供交互式命令行
const colors = require('colors') // 颜色模块
const {exec, execSync} = require("child_process"); // 启动一个新进程，用来执行命令
const {Spinner} = require("clui"); // 提供等待的状态
let loading = null

const $file = {
    // 判断文件是否存在
    exists: (path) => {
        return new Promise((resolve) => {
            resolve(fs.existsSync(path))
        })
    },
    // 创建文件夹
    mkDir: (path) => {
        return new Promise((resolve) => {
            fs.mkdir(path, (err => {
                if (!err) {
                    resolve(true)
                } else {
                    console.log(colors.red('创建文件夹失败'))
                    resolve(false)
                }
            }))
        })
    },
    // 删除整个文件夹
    rmDir: (path) => {
        return new Promise((resolve) => {
            fs.rmdir(path, {recursive: true, force: true}, (err => {
                if (!err) {
                    resolve(true)
                } else {
                    console.log(colors.red('文件夹删除失败'))
                    resolve(false)
                }
            }))
        })
    },
    // 复制整个文件夹
    copyDir: (OriginFilePath, CopyFilePath) => {
        //读取newFile文件夹下的文件
        fs.readdir(OriginFilePath, {withFileTypes: true}, (err, files) => {
            for (let file of files) {
                //判断是否是文件夹，不是则直接复制文件到newFile中
                if (!file.isDirectory()) {
                    //获取旧文件夹中要复制的文件
                    const OriginFile = path.resolve(OriginFilePath, file.name)
                    //获取新文件夹中复制的地方
                    const CopyFile = path.resolve(CopyFilePath, file.name)
                    //将文件从旧文件夹复制到新文件夹中
                    fs.copyFileSync(OriginFile, CopyFile)
                } else {//如果是文件夹就递归变量把最新的文件夹路径传过去
                    const CopyDirPath = path.resolve(CopyFilePath, file.name)
                    const OriginDirPath = path.resolve(OriginFilePath, file.name)
                    fs.mkdir(CopyDirPath, (err) => {

                    })
                    // OriginFilePath = OriginPath
                    // CopyFilePath = DirPath
                    $file.copyDir(OriginDirPath, CopyDirPath)
                }
            }
        })
    },
    // 文件读取
    readFile: (path) => {
        return new Promise((resolve) => {
            fs.readFile(path, {encoding: 'utf-8'}, ((err, data) => {
                if (!err) {
                    resolve(data)
                } else {
                    console.log(colors.red('文件读取失败'))
                    resolve(false)
                }
            }))
        })
    },
    // 文件写入
    writeFile: (path, data) => {
        return new Promise((resolve, reject) => {
            fs.writeFile(path, data, {
                encoding: "utf8",
                flag: "w",
                mode: 0o666
            }, err => {
                if (!err) {
                    resolve(true)
                } else {
                    console.log(colors.red('文件写入失败'))
                    resolve(false)
                }
            })
        })
    },
    // 获取git的文件夹
    getGitDir: (path) => {
        const start = path.lastIndexOf('/')
        const end = path.lastIndexOf('.')
        if (start !== -1 && end !== -1) {
            return path.slice(start + 1, end)
        }
        return ''
    },

    // 创建项目
    cloneProject: async (projectName, cmd) => {
        return new Promise(async (resolve, reject) => {
            // cli模板清单 通过git下载
            const cloneObj = {url: 'https://gitee.com/luzhaoqi/cli-template-json.git', fileName: 'cli.json'}
            // 根目录
            const rootPath = process.cwd()
            // 新工程目录
            const currentDirPath = rootPath + '\\' + projectName

            /* 第一步 创建工程目录 */
            // 判断新工程目录文件夹存不存在
            const exists = await $file.exists(currentDirPath)
            // 如果是覆盖目标目录，并且目录存在
            if (cmd.force) {
                // force 当为 true 时，如果 path 不存在，则异常将被忽略
                // recursive 如果为 true，则执行递归目录删除
                // 删除目录工程目录
                exists && await $file.rmDir(currentDirPath)

                // 创建工程目录
                await $file.mkDir(currentDirPath)
            } else {
                // 如果工程目录不存在
                if (!exists) {
                    // 创建工程目录
                    await $file.mkDir(currentDirPath)
                } else {
                    // 给出存在提示
                    console.log(colors.red('目标目录已存在，请修改 project-name ！'))
                    process.exit();
                }
            }

            /* 第二步 给出模板列表 */
            // 给出下载的提示
            loading = new Spinner('正在下载模板列表...')
            loading.start();
            // 克隆脚手架模板列表
            exec(`cd ${projectName} & git clone ${cloneObj.url}`, async (error) => {
                loading.stop();
                if (error) {
                    console.log(colors.red("发生了一个错误：" + JSON.stringify(error)));
                    process.exit();
                }
                // 模板目录
                const templateDirPath = currentDirPath + '\\' + $file.getGitDir(cloneObj.url)
                // 读取模板列表文件
                const cliFile = JSON.parse(await $file.readFile(templateDirPath + '\\' + cloneObj.fileName)).map(o=>{
                    o.value  =  `https://gitee.com/luzhaoqi/${o.value}.git`
                    return o
                })
                // 删除模板列表
                await $file.rmDir(templateDirPath)
                /* 第三步 用户选择模板 */
                // 给用户选择需要什么模板
                const answers = await inquirer.prompt([
                    {
                        type: 'list',
                        name: 'url',
                        message: '请选择框架模板',
                        choices: cliFile,
                    }
                ])

                const chooseItem = cliFile.find(item => {
                    return item.value === answers.url
                })

                loading = new Spinner(`正在下载(${colors.green(chooseItem.name)})...`)
                loading.start();
                exec(`cd ${projectName} & git clone ${answers.url}`, async (error) => {
                    loading.stop();
                    if (error) {
                        console.log(colors.red("发生了一个错误：" + JSON.stringify(error)));
                        process.exit();
                    }
                    // 对模板文件修修改改
                    loading = new Spinner(`初始化模板文件(${colors.green(chooseItem.name)})...`)
                    loading.start();
                    // 模板文件目录
                    const targetDirPath = currentDirPath + '\\' + $file.getGitDir(answers.url)
                    // 如果有.git文件 则删除
                    if (await $file.exists(targetDirPath + '\\' + '.git')) {
                        await $file.rmDir(targetDirPath + '\\' + '.git')
                    }
                    // 如果有package.json 则修改里面的name属性
                    if (await $file.exists(targetDirPath + '\\' + 'package.json')) {
                        const packageFile = JSON.parse(await $file.readFile(targetDirPath + '\\' + 'package.json'))
                        packageFile.name = projectName
                        packageFile.version = '1.0.0'
                        packageFile.description = ''
                        await $file.writeFile(targetDirPath + '\\' + 'package.json', JSON.stringify(packageFile, null, 4))
                    }
                    await $file.copyDir(targetDirPath, currentDirPath)
                    await $file.rmDir(targetDirPath)
                    new Promise(() => {
                        loading.stop();
                        console.log(colors.green("工程初始化完毕！！！"))
                        resolve(true)
                    })
                })
            })
        })
    },
}

module.exports = $file
